home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993…ch: Other People's Memory / ADC Developer CD (1993-03) (''Other People's Memory'')_iso / Dev.CD Mar 93.iso / Development Platforms / Apple II / Essentials / Technical.Notes / IIGS / TN.IIGS.094 < prev    next >
Encoding:
Text File  |  1992-07-15  |  10.7 KB  |  227 lines  |  [TEXT/GEOL]

  1. Apple II
  2. Technical Notes
  3. _____________________________________________________________________________
  4.                                                   Developer Technical Support
  5. Apple IIgs
  6. #94: Packing It In (and Out)
  7.  
  8. Revised by: Dave Lyons                                               May 1992
  9. Written by: C.K. Haun <TR>                                     September 1990
  10.  
  11. This Technical Note discusses a potential problem with the Miscellaneous Tools
  12. routine UnPackBytes.
  13.  
  14. CHANGES SINCE SEPTEMBER 1990: Noted that the problem detecting the end of the
  15. unpack-to buffer near the end of a bank is fixed in System 6.0.
  16. _____________________________________________________________________________
  17.  
  18.  
  19. PackBytes and UnPackBytes are handy data compression and expansion routines
  20. built into the Apple IIgs System Software.  Using them can dramatically reduce
  21. the amount of space your application uses on disk or in memory, but you need
  22. to understand how these calls work to avoid problems in your applications.
  23.  
  24.  
  25. BUFFER SIZE, BUFFER SIZE, BUFF, BUFF, BUFFER SIZE
  26.  
  27. There are some situations where the Miscellaneous Tools call UnPackBytes does
  28. not function as expected and can cause your application to loop infinitely
  29. while you're waiting for an unpacking process to finish.
  30.  
  31. The following packed data and code (in APW assembly) demonstrates the problem.
  32. It shows a small routine that unpacks data in two steps, simulating the
  33. situation in many applications where an arbitrary amount of data is unpacked
  34. in a variable amount of unpacking actions, depending on the results of the
  35. last unpack pass.
  36.  
  37. UnPackBuffer      ds    160                     ; area to unpack the data to
  38. UnPackBufferPtr   dc    i4'UnPackBuffer'        ; pointer to unpacking buffer
  39. UnPackBufferSize  ds    2
  40. temp              ds    2
  41.  
  42. PackedData        dc h'FFFFFFFF'
  43. EndPackData       anop
  44. PackLength        dc i2'EndPackData-PackedData' ; how many bytes of packed
  45. data
  46.  
  47. * In packbytes format $FFFF means '64 repeats of the next byte ($FF) taken as
  48. * 4 bytes' as described on page 14-39 of Toolbox Reference, so
  49. * this data should unpack into 512 $FF bytes
  50.  
  51. * The following code loops infinitely
  52.  
  53.                   lda   #160                    ; Unpack buffer size
  54.                   sta   UnPackBufferSize
  55. UnPackLoop        pea   0                       ; return space
  56.                   pushlong #PackedData          ; pointer to packed data
  57.                   pea   2                       ; size of the packed data,
  58.                                                 ; unpack two bytes
  59.                                                 ; at a time
  60.                   pushlong #UnPackBufferPtr     ; pointer to pointer to
  61.                                                 ; unpacking buffer
  62.                   pushlong #UnPackBufferSize    ; pointer to word with the
  63.                                                 ; size of the
  64.                                                 ;  unpacking buffer
  65.                   _UnPackBytes
  66.                   pla                           ; returns 0 bytes unpacked
  67.                   sta   temp
  68.                   lda   PackLength
  69.                   sec
  70.                   sbc   temp                    ; subtracting it from our
  71.                                                 ; known
  72.                   sta   PackLength              ; length of packed data
  73.                   bne   UnPackLoop              ; this is always be non-zero
  74.  
  75. The problem is in the data and the buffer size.  UnPackBytes is being told to
  76. unpack two bytes ($FFFF), which generate 256 bytes of unpacked data, into a
  77. 160-byte buffer.  Instead of reporting an error with this condition,
  78. UnPackBytes instead just does nothing and passes back zero as the returned
  79. number of bytes unpacked.  If you are relying on the unpacked byte count
  80. returned to control your unpacking loop, then you may encounter this problem.
  81.  
  82. UnPackBytes can be used to unpack in multiple steps, of course, but it cannot
  83. unpack a partial record.  It cannot unpack 160 bytes of the 256 bytes
  84. specified in this record because UnPackBytes does not maintain any state
  85. information, so it must unpack full records or do nothing.  If the buffer had
  86. been 256 bytes, this call would have succeeded.
  87.  
  88.  
  89. THE FIX
  90.  
  91. Fortunately, it's easy to avoid this situation if  you know that it can exist.
  92. Simply, always supply UnPackBytes with a buffer that is big enough for it to
  93. unpack at least two bytes (a flag or count byte and a data byte).  The largest
  94. value of a flag or count word possible is $FF, 64 repeats of the next byte
  95. taken as four bytes, which generates 256 unpacked bytes.  So always give
  96. UnPackBytes a 256-byte long output buffer and you should never encounter this
  97. problem.
  98.  
  99.  
  100. CHECK YOUR CURRENT APPLICATIONS
  101.  
  102. Please check your current applications to see if you could encounter this
  103. problem.  One of the most likely places for this error to occur is in
  104. applications that process Apple Preferred (file type $C0, auxiliary type
  105. $0002) pictures.  While most pictures currently available are screen-width or
  106. less (160 bytes or less per scan line), the Apple Preferred format and
  107. QuickDraw II both support pictures that are wider than the current Apple IIgs
  108. screen.  If someone has created a picture with a PixelsPerScanLine value of
  109. 1,280 with a ModeWord of $0080, it would generate a scan line that was 320
  110. bytes long.  If a scan line in this hypothetical picture were all white, for
  111. example, the first two bytes of the packed scan line would be $FFFF, and
  112. applications that assume a standard maximum 160 bytes per scan line would not
  113. handle this correctly.
  114.  
  115.  
  116. BUT THAT'S NOT ALL...
  117.  
  118. In System Software earlier than 6.0, UnPackBytes has some other buffering
  119. problems of which you need to be aware.  The size and location of the input
  120. buffer (the buffer containing your packed data) can also cause problems.
  121.  
  122. You can ignore this section if your application requires System 6.0.
  123.  
  124.    NOTE : These problems only occur if you are doing multipass
  125.           unpacks.  If you always unpack a packed data range in
  126.           one pass (with one call to UnPackBytes for the whole
  127.           data set) then you are not affected by these problems,
  128.           and the restrictions described herein do not apply.
  129.  
  130. MULTIPASS RESTRICTIONS
  131.  
  132. When performing a multipass unpack (as described on pp. 14-43..44 of the Apple
  133. IIgs Toolbox Reference, Volume 1) the packed data needs to follow two rules.
  134.  
  135. Rule 1: Your packed data buffer cannot cross a bank boundary.
  136. Rule 2: Your packed data buffer needs to be at least 65 bytes longer than the
  137.         actual size of the data.
  138.  
  139. These rules are required by a bug in UnPackBytes.  When UnPackBytes begins to
  140. unpack a record, it checks the record data to see if there are enough bytes in
  141. the current source buffer to unpack the number of bytes requested in the
  142. record header (described on pg. 14-39 of the Apple IIgs Toolbox Reference,
  143. Volume 1).  If there are not enough bytes left for the current record (i.e.,
  144. the header says to process 63 bytes, and there are only 30 left in the
  145. buffer), UnPackBytes returns to the caller.  The caller then adjusts the
  146. source buffer for the next pass based on the amount of actual bytes unpacked,
  147. so the bytes left over from the last pass get processed the next time.
  148.  
  149. The problem occurs when the partial record is close to the end of a bank.
  150. When UnPackBytes checks to see if there is enough data left in the buffer, the
  151. check is flawed when the real end of the buffer is near the end of a bank, and
  152. a complete copy of the partial record would extend into the next bank.
  153. UnPackBytes erroneously thinks that the record is complete, and happily
  154. unpacks the remaining actual packed data, plus random information from the
  155. next bank.  It continues to unpack nonsense data until it fills the unpacking
  156. buffer and the number of bytes unpacked returned by the UnPackBytes call is
  157. greater than the bufferSize parameter passed as input.
  158.  
  159. To prevent this bug from occurring, you need to make sure that the buffer for
  160. the packed data is at least one record length away from the end of a memory
  161. bank.  Since the largest packed data record is one flag byte and 64 data
  162. bytes, adding 65 bytes to the end of your buffer does the trick.  This ensures
  163. that your packed data is 65 bytes away from the end.
  164.  
  165. Following is an example of a safe way to prepare your packed data buffer for
  166. multipass unpacking, in APW assembly:
  167.  
  168.  
  169. * Some data space
  170. myCallBlock  dc     i2'2'                ; two parameters
  171. fileRefNum   ds     2                    ; file reference number
  172. EOFreturned  ds     4                    ; file length returned by this call
  173. myIDNumber   ds     2                    ; your application memory manager ID
  174. number
  175. * assume that a packed data file is open, and it's a plain packed screen
  176. image, not over 32K
  177.              jsl    $E100A8              ; ask GS/OS for the length of the
  178. data
  179.              dc     i2'$2019'            ; Get_EOF call
  180.              dc     i4'myCallBlock'
  181.  
  182. * Now we need a handle to read it into
  183.              pha
  184.              pha                         ; return space
  185.              pea    0                    ; size, high word
  186.              lda    EOFreturned          ; the actual size of the packed data
  187.              sta    actualPackDataSize
  188.              clc
  189.              adc    #65                  ; ask for a handle 65 bytes longer
  190.                                          ; than the data
  191.              pha
  192.              lda    myIDnumber           ; Memory Manager ID for your
  193.                                          ; application
  194.              pha
  195.              pea    $8010                ; attrLocked and attrNoCross
  196.              pea    0
  197.              pea    0                    ; anywhere
  198.              _NewHandle                  ; get the handle
  199.  
  200. Now you have a handle 65 bytes longer than your data that does not cross a
  201. bank boundary.  You are ready to read in the data and perform a multipass
  202. unpack.
  203.  
  204.  
  205. PACKBYTES BUFFERS COUNT TOO
  206.  
  207. PackBytes can also cause you problems if you do not plan for the worst-case
  208. situation.  Unlike the other toolbox compression routine ACECompress,
  209. PackBytes is not guaranteed to shrink the source data.  In fact, your data
  210. size may actually grow after a PackBytes call.
  211.  
  212. If you pass a data stream of 64 bytes, all with different values, to
  213. PackBytes, PackBytes puts 65 bytes in your output buffer--the 64 original data
  214. bytes and the flag byte of $3F, indicating "64 bytes follow, all different."
  215. Unless you preprocess or analyze your data before packing to avoid this
  216. situation, make sure your output buffer is large enough to hold the worst case
  217. situation, one additional byte generated for every 64 bytes passed to
  218. PackBytes for compression.
  219.  
  220.  
  221. Further Reference
  222. _____________________________________________________________________________
  223.  
  224.    o   Apple IIgs Toolbox Reference, Volumes 1-3
  225.    o   File Type Note for File Type $C0, Auxiliary Type $0002, Apple
  226.        Preferred Format
  227.